package com.jourwon.spring.boot.mapper;

import com.jourwon.spring.boot.dto.DoctorDto;
import com.jourwon.spring.boot.entity.*;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;

import javax.validation.ValidationException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author JourWon
 * @date 2023/4/3
 */
@Mapper(componentModel = "spring", uses = {PatientMapper.class, Validator.class}, imports = {LocalDateTime.class, UUID.class})
public interface DoctorMapper {

    // DoctorMapper INSTANCE = Mappers.getMapper(DoctorMapper.class);

    /**
     * 实体类转换方法
     *
     * @param doctor doctor
     * @return Set<DoctorDto>
     */
    Set<DoctorDto> setConvert(Set<Doctor> doctor);

    /**
     * 实体类转换方法
     *
     * @param doctor doctor
     * @return Map<String, DoctorDto>
     */
    Map<String, DoctorDto> mapConvert(Map<String, Doctor> doctor);

    /**
     * 实体类转换方法
     *
     * @param doctor doctor
     * @return DoctorDto
     */
    @Named(value = "toDto")
    @Mapping(target = "id", constant = "-1")
    @Mapping(source = "doctor.patientList", target = "patientDtoList")
    @Mapping(source = "doctor.specialty", target = "specialization", defaultValue = "Information Not Available")
    DoctorDto toDto(Doctor doctor);

    /**
     * 实体类转换方法
     *
     * @param doctor doctor
     * @return DoctorDto
     */
    @Named(value = "toDtoWithExpression")
    @Mapping(target = "externalId", expression = "java(UUID.randomUUID().toString())")
    @Mapping(source = "doctor.availability", target = "availability", defaultExpression = "java(LocalDateTime.now())")
    @Mapping(source = "doctor.patientList", target = "patientDtoList")
    @Mapping(source = "doctor.specialty", target = "specialization")
    DoctorDto toDtoWithExpression(Doctor doctor);

    /**
     * 实体类转换方法
     *
     * @param doctor doctor
     * @return DoctorDto
     * @throws ValidationException
     */
    @Named(value = "toDtoThrows")
    @Mapping(source = "doctor.patientList", target = "patientDtoList")
    @Mapping(source = "doctor.specialty", target = "specialization")
    DoctorDto toDtoThrows(Doctor doctor) throws ValidationException;

    /**
     * 实体类转换方法
     *
     * @param doctor    doctor
     * @param education education
     * @return DoctorPatientSummary
     */
    default DoctorPatientSummary toDoctorPatientSummary(Doctor doctor, Education education) {
        return DoctorPatientSummary.builder()
                .doctorId(doctor.getId())
                .doctorName(doctor.getName())
                .patientCount(doctor.getPatientList().size())
                .patientIds(doctor.getPatientList()
                        .stream()
                        .map(Patient::getId)
                        .collect(Collectors.toList()))
                .institute(education.getInstitute())
                .specialization(education.getDegreeName())
                .build();
    }

}
